package guet.imagan.util;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * 类工具，
 */
public class ClassUtil {

	/**
	 * 查找当前应用程序类路径下的一个包（及其子包）下的所有完全类名
	 * @param packageName 包名，例如："guet.imagan"
	 * @return 所有类集合
	 */
	public static List<String> findClassNames(String packageName){
		List<String>classNames=new LinkedList<>();
		String packageDirName=packageName.replace('.','/');
		Enumeration<URL> dirs;
		try {
			dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
		} catch (IOException e) {
			return classNames;
		}
		while(dirs.hasMoreElements()){
			URL url = dirs.nextElement();
			//获取协议名称
			String protocol=url.getProtocol();
			//如果包以文件的形式存放
			if("file".equals(protocol)){

				String filePath= null;
				try {
					filePath = URLDecoder.decode(url.getFile(),"utf-8");
				} catch (UnsupportedEncodingException e) {
					continue;
				}
				findClassNames(classNames,filePath);

			}else if("jar".equals(protocol)){
				JarFile jar;
				try {
					jar = ((JarURLConnection) url.openConnection()).getJarFile();
				} catch (IOException e) {
					continue;
				}
				findClassNames(classNames,jar,packageDirName);

			}
		}
		List<String>result=new LinkedList<>();
		classNames.forEach(className->result.add(packageName+"."+className));
		return result;
	}

	/**
	 * 在某个类文件搜素根目录下（包括其子目录），查找所有的类的完全限定名
	 * @param classNames 存储查找结果
	 * @param filePath 类文件搜素根目录
	 */
	public static void findClassNames(List<String> classNames, String filePath) {
		File dir=new File(filePath);
		List<File>files=new LinkedList<>();
		FileUtil.findFiles(files,dir, Collections.singletonList("class"));
		List<String>relativeFilePaths=FileUtil.getRelativePath(dir,files);
		relativeFilePaths.forEach(path ->{
			String tmpStr=path.substring(0,path.lastIndexOf("."));
			String res=tmpStr.replace(File.separator,".");
			classNames.add(res);
		});
	}

	/**
	 * 在一个jar文件中查找具有指定包路径的类,把类的完整名保存下来
	 * @param classNames 存储查找结果
	 * @param jar jar文件
	 * @param packageDirName 包路径，例如：guet/imagan
	 */
	public static void findClassNames(List<String>classNames, JarFile jar, String packageDirName){
		Enumeration<JarEntry> entries = jar.entries();
		while(entries.hasMoreElements()){
			JarEntry jarEntry = entries.nextElement();
			String name=jarEntry.getName();
			if(name.charAt(0)=='/'){
				name=name.substring(1);
			}
			if(name.startsWith(packageDirName)){
				int idx = name.lastIndexOf('/');
				//当name是一个包时
				if(idx!=-1){
					//获取包名
					String pckName = name.substring(0,idx).replace('/','.');
					if(!jarEntry.isDirectory()&&name.endsWith(".class")){
						String className = name.substring(pckName.length() + 1,
								name.length() - 6);
						classNames.add(className);
					}
				}
			}
		}
	}


}
